﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Threading;

namespace Compte
{
    public partial class frmCompte : Form
    {
        private Utilisateur user;
        private enum Affichage { Tous, User, Rien}
        private ComposanteSQL bdAccess;

        public frmCompte()
        {
            InitializeComponent();
            bdAccess = new ComposanteSQL(ComposanteSQL.Access.OleDB, @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + System.Windows.Forms.Application.StartupPath + @"\Budget.accdb;Persist Security Info=False;");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            aiCalendrier.SetDisplayDate(DateTime.Now.Year, DateTime.Now.Month);
            setAffichage(Affichage.Rien);
        }

        //Inscrit/connect l'utilisateur
        public void setUser(String nom)
        {
            List<Utilisateur> u = bdAccess.SelectGeneric<Utilisateur>("select Nom, Solde from Utilisateur where Nom = @nom", Utilisateur.GetParam(2), new SQLParameter[] { new SQLParameter("@nom", nom) });
            if (u.Count == 0)
            {
                if (MessageBox.Show("Cet usager n'existe pas. Voulez-vous créer cet usager?", "Usager non trouvé", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    bdAccess.Insert<Utilisateur>(new Utilisateur(nom, 0));
                    bdAccess.Insert<Compte>(new Compte("Principale", 0m, nom));
                    u = bdAccess.SelectGeneric<Utilisateur>("select Nom, Solde from Utilisateur where Nom = @nom", Utilisateur.GetParam(2), new SQLParameter[] { new SQLParameter("@nom", nom) });
                    user = u[0];
                    this.Text = user.ToString();
                }
                else
                    return;
            }
            List<Compte> c = bdAccess.SelectGeneric<Compte>("select Nom, Solde, NomUtilisateur from Compte where NomUtilisateur = @nom", Compte.GetParam(3), new SQLParameter[] { new SQLParameter("@nom", nom) });
            cboCompte.Items.AddRange(c.ToArray());
            cboCompte.SelectedIndex = 0;
            setCompte((Compte)cboCompte.SelectedItem);
            setAffichage(Affichage.Tous);
        }

        private Compte getCompte()
        {
            return (Compte)cboCompte.Tag;
        }
        private void setCompte(Compte c)
        {
            cboCompte.Tag = c;
            List<Object[]> tout = bdAccess.SelectObject("select No, Nom, Montant from ActifPassif");
            foreach (Object[] obj in tout)
            {
                dgvTout.Rows.Add(obj);
            }
            setInfo(new ActifPassif());
            gbActPaf.Tag = null;
            lblSolde.Text = "Solde : " + c.Solde;
        }

        //Obtient ActifPassif dans gbActPaf
        private ActifPassif getInfo()
        {
            Regex bignumber = new Regex(@"^\d+([\.|,]\d{1,2})?$");
            Regex smallnumber = new Regex(@"^0[\.|,]\d{1,2}$");
            ActifPassif ap;
            Decimal montant = 0.0m;
            ActifPassif.Action act = rbtnRevenu.Checked ? ActifPassif.Action.Revenu : rbtnPayement.Checked ? ActifPassif.Action.Payement : ActifPassif.Action.Transfert;
            if (bignumber.IsMatch(txtMontant.Text) || smallnumber.IsMatch(txtMontant.Text)) { montant = Decimal.Parse(txtMontant.Text); }
            else { return null; }
            ap = new ActifPassif(montant, DateTime.Now, act, ((Compte)cboCompte.SelectedItem).Nom,"");
            if (txtNom.Text != "") { ap.Nom = txtNom.Text; }
            if ((int)numFois.Value > 1)
            {
                ActifPassif.Evenement e;
                if (rbtnJour.Checked)
                    e = ActifPassif.Evenement.Jour;
                else if (rbtnSemaine.Checked)
                    e = ActifPassif.Evenement.Semaine;
                else if (rbtnMois.Checked)
                    e = ActifPassif.Evenement.Mois;
                else if (rbtnAn.Checked)
                    e = ActifPassif.Evenement.Annee;
                else
                    return null;
                ap.Frequence = e;
                ap.Debut = dtpDebut.Value;
                ap.Fin = dtpFin.Value;
                ap.NbFrequence = (int)numTemps.Value;
                ap.NbFois = (int)numFois.Value;
            }
            return ap;
        }
        //Afficher ActifPassif dans gbActPaf
        private void setInfo(ActifPassif ap)
        {
            gbActPaf.Tag = ap.No;
            txtNom.Text = ap.Nom == null || ap.Nom == "" ? "" : ap.Nom;
            txtMontant.Text = ap.Montant.ToString();
            rbtnPayement.Checked = ap.Actif == ActifPassif.Action.Payement;
            rbtnRevenu.Checked = ap.Actif == ActifPassif.Action.Revenu;
            rbtnTransfert.Checked = ap.Actif == ActifPassif.Action.Transfert;
            if (ap.NbFois > 1)
            {
                rbtnAn.Checked = ap.Frequence == ActifPassif.Evenement.Annee;
                rbtnMois.Checked = ap.Frequence == ActifPassif.Evenement.Mois;
                rbtnSemaine.Checked = ap.Frequence == ActifPassif.Evenement.Semaine;
                rbtnJour.Checked = ap.Frequence == ActifPassif.Evenement.Jour;
                numTemps.Value = (decimal)ap.NbFrequence;
                numFois.Value = (decimal)ap.NbFois;
                dtpDebut.Value = ap.Debut;
                dtpFin.Value = ap.Fin;
            }
            else
            {
                rbtnAn.Checked = false;
                rbtnMois.Checked = false;
                rbtnSemaine.Checked = false;
                rbtnJour.Checked = false;
                numTemps.Value = (decimal)0;
                numFois.Value = (decimal)0;
                dtpDebut.Value = DateTime.Now;
                dtpFin.Value = DateTime.Now.AddDays(-1);
            }
        }

        //Set l'affichage du programme
        private void setAffichage(Affichage mode)
        {
            if (mode == Affichage.Rien)
            {
                aiCalendrier.Visible = false;
                lblActifPassifJour.Visible = false;
                lblActifPassifTous.Visible = false;
                dgvJour.Visible = false;
                dgvTout.Visible = false;
                gbActPaf.Visible = false;
                gbCompte.Visible = false;
                gbUser.Visible = true;
            }
            else if (mode == Affichage.Tous)
            {
                aiCalendrier.Visible = true;
                lblActifPassifJour.Visible = true;
                lblActifPassifTous.Visible = true;
                dgvJour.Visible = true;
                dgvTout.Visible = true;
                gbActPaf.Visible = true;
                gbCompte.Visible = true;
                gbUser.Visible = true;
            }
            else
            {
                aiCalendrier.Visible = false;
                lblActifPassifJour.Visible = false;
                lblActifPassifTous.Visible = false;
                dgvJour.Visible = false;
                dgvTout.Visible = false;
                gbActPaf.Visible = false;
                gbCompte.Visible = true;
                gbUser.Visible = true;
            }
        }

        //Vérifie tous les comptes voir s'il n'y aurrait pas ActifPassif à faire une action
        private void verification()
        {
            List<Compte> cs = bdAccess.SelectGeneric<Compte>("select Nom, Solde, NomUtilisateur from Compte where NomUtilisateur = @nom", Compte.GetParam(3), new SQLParameter[] { new SQLParameter("@nom", user.Nom) });
            foreach (Compte c in cs)
            {
                List<ActifPassif> aps = bdAccess.SelectGeneric<ActifPassif>("select No, Nom, Montant, Moment, Frequence, NbFrequence, Debut, NbFois, Fin, Actif, NoCompte, NoTransfert from ActifPassif where NbFois > 0", ActifPassif.GetParam(12));
                foreach (ActifPassif ap in aps)
                {
                    //si debut est aujourd'hui ou si il est dans une fréquence d'activation
                    while (ap.CanDoAction())
                    {
                        doOperation(c, ap);
                    }
                }
            }
        }
        private void doOperation(Compte c, ActifPassif ap)
        {
            if (ap.Actif == ActifPassif.Action.Revenu)
                c.Solde += ap.Montant;
            else if (ap.Actif == ActifPassif.Action.Payement)
                c.Solde -= ap.Montant;
            else
            {
                Compte autre = bdAccess.SelectGeneric<Compte>("select Nom, Solde, NomUtilisateur from Compte where NomUtilisateur = @nomUser and Nom = @nomCompte", Compte.GetParam(3), new SQLParameter[] { new SQLParameter("@nomUser", user.Nom), new SQLParameter("nomCompte", ap.NomTransfert) })[0];
                c.Solde -= ap.Montant;
                autre.Solde += ap.Montant;
                bdAccess.Update(autre);
            }
            ap.NbFois--;
            bdAccess.Update(c);
            bdAccess.Update(ap);
            lblSolde.Text = "Solde : " + c.Solde;
        }

        private void dgvJour_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            String requete = "select No, Nom, Montant, Moment, Frequence, NbFrequence, Debut, NbFois, Fin, Actif, NoCompte, NoTransfert from ActifPassif where No = '" + dgvJour.SelectedRows[0].Cells[0].Value.ToString() + "';";
            Type[] t = ActifPassif.GetParam(12);
            ActifPassif ap = bdAccess.SelectGeneric<ActifPassif>(requete, t)[0];
            setInfo(ap);
        }

        private void dgvTout_SelectionChanged(object sender, EventArgs e)
        {
            String requete = "select No, Nom, Montant, Moment, Frequence, NbFrequence, Debut, NbFois, Fin, Actif, NoCompte, NoTransfert from ActifPassif where No = '" + dgvTout.SelectedRows[0].Cells[0].Value.ToString() + "';";
            Type[] t = ActifPassif.GetParam(12);
            ActifPassif ap = bdAccess.SelectGeneric<ActifPassif>(requete, t)[0];
            setInfo(ap);
        }

        private void btnAddMod_Click(object sender, EventArgs e)
        {
            ActifPassif ap = getInfo();
            if (ap != null)
            {
                if (ap.Nom != "")
                {
                    if (bdAccess.SelectObject("select * from ActifPassif where Nom = '" + ap.Nom + "';").Count == 0)
                        bdAccess.Insert(ap);
                    else
                    {
                        if (gbActPaf.Tag != null)
                        {
                            ap.No = ((ActifPassif)gbActPaf.Tag).No;
                            bdAccess.Update(ap);
                        }
                    }
                }
                else
                    bdAccess.Insert(getInfo());
                if (ap.CanDoAction())
                    doOperation(getCompte(), ap);
            }
        }

        private void btnEfface_Click(object sender, EventArgs e)
        {
            setInfo(new ActifPassif());
            gbActPaf.Tag = null;
        }

        private void btnSupprime_Click(object sender, EventArgs e)
        {
            if (txtNom.Text != "")
            {
                if (bdAccess.SelectObject("select * from ActifPassif where Nom = '" + txtNom.Text + "';").Count > 0 && gbActPaf.Tag != null)
                {
                    ActifPassif ap = getInfo();
                    ap.No = ((ActifPassif)gbActPaf.Tag).No;
                    bdAccess.Update(ap);
                }
            }
        }

        private void btnAjouter_Click(object sender, EventArgs e)
        {
            for (int a = 0; a < cboCompte.Items.Count; a++)
            {
                if (cboCompte.Text == cboCompte.Items[a].ToString())
                    return;
            }
            Compte c = new Compte(cboCompte.Text, 0m, user.Nom);
            bdAccess.Insert<Compte>(c);
            cboCompte.Items.Add(c);
            cboCompte.SelectedIndex = 0;
            setCompte((Compte)cboCompte.SelectedItem);
        }

        private void btnSupprimer_Click(object sender, EventArgs e)
        {
            Compte c = (Compte)cboCompte.SelectedItem;
            if (c.Nom != "Principal")
            {
                if (c.Solde > 1m)
                {
                    for (int a = 0; a < cboCompte.Items.Count; a++)
                    {
                        if ("Principal" == cboCompte.Items[a].ToString())
                        {
                            ((Compte)cboCompte.Items[a]).Solde += c.Solde;
                            bdAccess.Update<Compte>((Compte)cboCompte.Items[a]);
                        }
                    }
                }
                bdAccess.Delete<Compte>(c);
                cboCompte.Items.RemoveAt(cboCompte.SelectedIndex);
                cboCompte.SelectedIndex = 0;
                setCompte((Compte)cboCompte.SelectedItem);
            }

        }

        private void btnlog_Click(object sender, EventArgs e)
        {
            setUser(txtNomUser.Text);
        }

        private void aiCalendrier_CalendarDayClick(object sender, EventArgs e, AcceleratedIdeas.AICalendarEventArgs DayPanelArgs)
        {
            List<Object[]> now = bdAccess.SelectObject("select No, Nom, Montant from ActifPassif where Moment = @moment", new SQLParameter[] { new SQLParameter("@moment", DayPanelArgs.DayPanel.Date) });
            foreach(Object[] obj in now)
            {
                dgvJour.Rows.Add(obj);
            }
        }

        private void rbtnTransfert_CheckedChanged(object sender, EventArgs e)
        {
            if (rbtnTransfert.Checked)
            {
                List<Compte> c = bdAccess.SelectGeneric<Compte>("select Nom, Solde, NoUtilisateur from Compte where NoUtilisateur = 0 and Nom <> @nom", Compte.GetParam(3), new SQLParameter[] { new SQLParameter("@nom", getCompte().Nom) });
                cboTransaction.Items.AddRange(c.ToArray());
                lblTitreTransaction.Visible = true;
                cboTransaction.Visible = true;
            }
            else
            {
                cboTransaction.Items.Clear();
                lblTitreTransaction.Visible = false;
                cboTransaction.Visible = false;
            }
        }

        private void txtNomUser_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Enter)
                setUser(txtNomUser.Text);
        }
    }
}